<!--
SPDX-FileCopyrightText: syuilo and misskey-project
SPDX-License-Identifier: AGPL-3.0-only
-->

<template>
<div>
	<div v-if="achievements" :class="$style.root">
		<div v-for="achievement in achievements" :key="achievement.name" :class="$style.achievement" class="_panel">
			<div :class="$style.icon">
				<div
					:class="[$style.iconFrame, {
						[$style.iconFrame_bronze]: ACHIEVEMENT_BADGES[achievement.name].frame === 'bronze',
						[$style.iconFrame_silver]: ACHIEVEMENT_BADGES[achievement.name].frame === 'silver',
						[$style.iconFrame_gold]: ACHIEVEMENT_BADGES[achievement.name].frame === 'gold',
						[$style.iconFrame_platinum]: ACHIEVEMENT_BADGES[achievement.name].frame === 'platinum',
					}]"
				>
					<div :class="[$style.iconInner]" :style="{ background: ACHIEVEMENT_BADGES[achievement.name].bg ?? '' }">
						<img :class="$style.iconImg" :src="ACHIEVEMENT_BADGES[achievement.name].img">
					</div>
				</div>
			</div>
			<div :class="$style.body">
				<div :class="$style.header">
					<span :class="$style.title">{{ i18n.ts._achievements._types['_' + achievement.name].title }}</span>
					<span :class="$style.time">
						<time v-tooltip="new Date(achievement.unlockedAt).toLocaleString()">{{ new Date(achievement.unlockedAt).getFullYear() }}/{{ new Date(achievement.unlockedAt).getMonth() + 1 }}/{{ new Date(achievement.unlockedAt).getDate() }}</time>
					</span>
				</div>
				<div :class="$style.description">{{ withDescription ? i18n.ts._achievements._types['_' + achievement.name].description : '???' }}</div>
				<div v-if="i18n.ts._achievements._types['_' + achievement.name].flavor && withDescription" :class="$style.flavor">{{ i18n.ts._achievements._types['_' + achievement.name].flavor }}</div>
			</div>
		</div>
		<template v-if="withLocked">
			<div v-for="achievement in lockedAchievements" :key="achievement" :class="[$style.achievement, $style.locked]" class="_panel" @click="achievement === 'clickedClickHere' ? clickHere() : () => {}">
				<div :class="$style.icon">
				</div>
				<div :class="$style.body">
					<div :class="$style.header">
						<span :class="$style.title">???</span>
					</div>
					<div :class="$style.description">???</div>
				</div>
			</div>
		</template>
	</div>
	<div v-else>
		<MkLoading/>
	</div>
</div>
</template>

<script lang="ts" setup>
import * as Misskey from 'misskey-js';
import { onMounted, ref, computed } from 'vue';
import * as os from '@/os.js';
import { misskeyApi } from '@/utility/misskey-api.js';
import { i18n } from '@/i18n.js';
import { ACHIEVEMENT_TYPES, ACHIEVEMENT_BADGES, claimAchievement } from '@/utility/achievements.js';

const props = withDefaults(defineProps<{
	user: Misskey.entities.User;
	withLocked?: boolean;
	withDescription?: boolean;
}>(), {
	withLocked: true,
	withDescription: true,
});

const achievements = ref<Misskey.entities.UsersAchievementsResponse | null>(null);
const lockedAchievements = computed(() => ACHIEVEMENT_TYPES.filter(x => !(achievements.value ?? []).some(a => a.name === x)));

function _fetch_() {
	misskeyApi('users/achievements', { userId: props.user.id }).then(res => {
		achievements.value = [];
		for (const t of ACHIEVEMENT_TYPES) {
			const a = res.find(x => x.name === t);
			if (a) achievements.value.push(a);
		}
		//achievements = res.sort((a, b) => b.unlockedAt - a.unlockedAt);
	});
}

function clickHere() {
	claimAchievement('clickedClickHere');
	_fetch_();
}

onMounted(() => {
	_fetch_();
});
</script>

<style lang="scss" module>
.root {
	display: grid;
	grid-template-columns: repeat(auto-fill, min(380px, 100%));
	grid-gap: 12px;
	place-content: center;
}

.achievement {
	display: flex;
	padding: 16px;

	&.locked {
		opacity: 0.5;
	}
}

.icon {
	flex-shrink: 0;
	margin-right: 12px;
}

@keyframes shine {
	0% { translate: -30px; }
	100% { translate: -130px; }
}

.iconFrame {
	position: relative;
	width: 58px;
	height: 58px;
	padding: 6px;
	border-radius: 100%;
	box-sizing: border-box;
	pointer-events: none;
	user-select: none;
	filter: drop-shadow(0px 2px 2px #00000044);
	box-shadow: 0 1px 0px #ffffff88 inset;
	overflow: clip;
}
.iconFrame_bronze {
	background: linear-gradient(0deg, #703827, #d37566);

	> .iconInner {
		background: linear-gradient(0deg, #d37566, #703827);
	}
}
.iconFrame_silver {
	background: linear-gradient(0deg, #7c7c7c, #e1e1e1);

	> .iconInner {
		background: linear-gradient(0deg, #e1e1e1, #7c7c7c);
	}
}
.iconFrame_gold {
	background: linear-gradient(0deg, rgba(255,182,85,1) 0%, rgba(233,133,0,1) 49%, rgba(255,243,93,1) 51%, rgba(255,187,25,1) 100%);

	> .iconInner {
		background: linear-gradient(0deg, #ffee20, #eb7018);
	}

	&::before {
		content: "";
		display: block;
		position: absolute;
    top: 30px;
    width: 200px;
    height: 8px;
    rotate: -45deg;
    translate: -30px;
		background: #ffffff88;
		animation: shine 2s infinite;
	}
}
.iconFrame_platinum {
	background: linear-gradient(0deg, rgba(154,154,154,1) 0%, rgba(226,226,226,1) 49%, rgba(255,255,255,1) 51%, rgba(195,195,195,1) 100%);

	> .iconInner {
		background: linear-gradient(0deg, #e1e1e1, #7c7c7c);
	}

	&::before {
		content: "";
		display: block;
		position: absolute;
    top: 30px;
    width: 200px;
    height: 8px;
    rotate: -45deg;
    translate: -30px;
		background: #ffffffee;
		animation: shine 2s infinite;
	}
}

.iconInner {
	position: relative;
	width: 100%;
	height: 100%;
	border-radius: 100%;
	box-shadow: 0 1px 0px #ffffff88 inset;
}

.iconImg {
	width: calc(100% - 12px);
	height: calc(100% - 12px);
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	margin: auto;
	filter: drop-shadow(0px 1px 2px #000000aa);
}

.body {
	flex: 1;
	min-width: 0;
}

.header {
	margin-bottom: 8px;
	display: flex;
}

.title {
	font-weight: bold;
}

.time {
	margin-left: auto;
	font-size: 85%;
	opacity: 0.7;
}

.description {
	font-size: 85%;
}

.flavor {
	opacity: 0.7;
	transform: skewX(-15deg);
	font-size: 85%;
	margin-top: 8px;
}
</style>
